package cn.akwangl.service.async;

import cn.akwangl.pojo.VehicleTrack;
import cn.akwangl.pojo.bo.VehicleTrackQuery;
import cn.akwangl.service.IVehicleTrackService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;

/**
 * 行驶轨迹异步.
 *
 * @author 阿坤同学
 * @date 2022/7/8 14:23
 */
@Slf4j
@Service
public class VehicleTrackServiceAsync {

    /**
     * 当pageSize大于MAX_LIMIT则将分页拆成多个小分页异步查询.
     */
    private static final long MAX_LIMIT = 1000L;

    private IVehicleTrackService vehicleTrackService;

    @Autowired
    public void setVehicleTrackService(IVehicleTrackService vehicleTrackService) {
        this.vehicleTrackService = vehicleTrackService;
    }

    /**
     * 异步分页查询.
     * <p>
     * 当pageSize大于MAX_LIMIT则将分页拆成多个小分页异步查询.
     *
     * @param query 查询条件
     * @return 行驶轨迹集合
     * @author 阿坤同学
     * @date 2022/7/8 14:34
     * @since 0.0.7
     */
    public Page<VehicleTrack> list(VehicleTrackQuery query) {
        long pageNum = query.getPage();
        long pageSize = query.getPageSize();

        Page<VehicleTrack> page = new Page(pageNum, pageSize);
        try {
            if (pageSize > MAX_LIMIT) {
                List<VehicleTrack> voList = new ArrayList(Long.valueOf(pageSize).intValue());
                page.setRecords(voList);
                page.setTotal(vehicleTrackService.count());
                long shardingSize = pageSize / 10;
                long shardingNum = pageSize % shardingSize == 0 ? pageSize / shardingSize : pageSize / shardingSize + 1;

                List<Future<Page<VehicleTrack>>> list = new ArrayList(Long.valueOf(shardingNum).intValue());
                for (int i = 1; i <= shardingNum; i++) {
                    Future<Page<VehicleTrack>> pageFuture = page(i, shardingSize);
                    list.add(pageFuture);
                }

                for (Future<Page<VehicleTrack>> pageFuture : list) {
                    Page<VehicleTrack> shardingPage = pageFuture.get();
                    voList.addAll(shardingPage.getRecords());
                }
            } else {
                page = vehicleTrackService.page(page);
            }
        } catch (Exception e) {
            log.error("异步分页查询失败", e);
        }
        return page;
    }

    /**
     * 异步分页查询.
     * <p>
     * 此方法并不会查询总数.
     *
     * @param page     页码
     * @param PageSize 分页大小
     * @return Future
     * @author 阿坤同学
     * @date 2022/7/8 14:27
     * @since 0.0.7
     */
    @Async
    public Future<Page<VehicleTrack>> page(long page, long PageSize) {
        LambdaQueryWrapper<VehicleTrack> lambdaQuery = Wrappers.lambdaQuery();
        lambdaQuery.orderByAsc(VehicleTrack::getId);
        return new AsyncResult(vehicleTrackService.page(new Page(page, PageSize, false), lambdaQuery));
    }
}
